#include "TriGrid.h"

TriGrid::TriGrid()
{
}

TriGrid::TriGrid(int width, int depth, float dx, float dz)
: mWidth(width)
, mDepth(depth)
, mTileWidth(dx)
, mTileDepth(dz)
, WHITE(1.0f, 1.0f, 1.0f, 1.0f)
, BEACH_SAND(1.0f, 0.96f, 0.62f, 1.0f)
, LIGHT_GREEN(0.48f, 0.77f, 0.46f, 1.0f)
, DARK_GREEN(0.1f, 0.48f, 0.19f, 1.0f)
, DARK_BROWN(0.45f, 0.39f, 0.34f, 1.0f)
{
	mNumVertices = (++width) * (++depth);
	mNumFaces = width * depth * 2;

	BuildVertexBuffer();
	BuildIndexBuffer();

	D3DXCreateEffectFromFile(gD3DDevice, "Transform.fx", 0, 0, D3DXSHADER_DEBUG, 0, &mFx, &mErrors);
	if (mErrors)
	{
		MessageBox(0, (char*)mErrors->GetBufferPointer(), 0, 0);
	}

	mhTech = mFx->GetTechniqueByName("FogTech");
	mhWVP = mFx->GetParameterByName(0, "gWVP");
	mhTime = mFx->GetParameterByName(0, "gTime");
	mhEyePos = mFx->GetParameterByName(0, "gEyePos");
	mhFogColor = mFx->GetParameterByName(0, "gFogColor");
	mhFogMinDist = mFx->GetParameterByName(0, "minDist");
	mhFogMaxDist = mFx->GetParameterByName(0, "maxDist");

	mFx->SetVector(mhFogColor, &D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f));
	mFx->SetFloat(mhFogMinDist, 0.0f);
	mFx->SetFloat(mhFogMaxDist, 100.0f);

	mFx->SetTechnique(mhTech);
}

TriGrid::~TriGrid()
{

}

void TriGrid::Update(double dt)
{
	mFx->SetFloat(mhTime, gTimer->GetGameTime());
	mFx->SetValue(mhEyePos, gD3DApp->GetCameraPosition(), sizeof(D3DXVECTOR3));
}

void TriGrid::Draw(ID3DXSprite& sprite, D3DXMATRIX& view, D3DXMATRIX& proj)
{
	HR(gD3DDevice->SetStreamSource(0, mVB, 0, sizeof(VertexPosCol)));
	HR(gD3DDevice->SetVertexDeclaration(VertexPosCol::decl));
	HR(gD3DDevice->SetIndices(mIB));

	D3DXMATRIX world;
	D3DXMatrixIdentity(&world);
	mFx->SetMatrix(mhWVP, &(world * view * proj));

	UINT numPasses = 0;
	mFx->Begin(&numPasses, 0);
	for (UINT i = 0; i < numPasses; i++)
	{
		mFx->BeginPass(i);
		HR(gD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mNumVertices, 0, mNumFaces));
		mFx->EndPass();
	}
	mFx->End();
}

void TriGrid::BuildVertexBuffer()
{
	HR(gD3DDevice->CreateVertexBuffer(mNumVertices * sizeof(VertexPosCol),
		D3DUSAGE_WRITEONLY,
		0, D3DPOOL_MANAGED,
		&mVB, 0));

	VertexPosCol* vertices = 0;
	HR(mVB->Lock(0, 0, (void**)&vertices, 0));

	float halfWidth = (mWidth - 1) * mTileWidth * 0.5f;
	float halfDepth = (mDepth - 1) * mTileDepth * 0.5f;
	for (unsigned int i = 0; i < mWidth; ++i)
	{
		float z = halfDepth - i * mTileWidth;
		for (unsigned int j = 0; j < mDepth; ++j)
		{
			float x = -halfWidth + j * mTileWidth;
			float y = GetHeight(x, z, 0.1f, 0.22f);

			if (y < -1.0f)
			{
				vertices[i * mDepth + j].col = BEACH_SAND;
			}
			else if (y < 1.0f)
			{
				vertices[i * mDepth + j].col = LIGHT_GREEN;
			}
			else if (y < 3.0f)
			{
				vertices[i * mDepth + j].col = DARK_GREEN;
			}
			else if (y < 5.0f)
			{
				vertices[i * mDepth + j].col = DARK_BROWN;
			}
			else
			{
				vertices[i * mDepth + j].col = WHITE;
			}

			vertices[i * mDepth + j].pos = D3DXVECTOR3(x, y, z);
			//vertices[i * mDepth + j].col = D3DCOLOR_XRGB(255, 0, 0);
		}
	}

	HR(mVB->Unlock());
}

void TriGrid::BuildIndexBuffer()
{
	HR(gD3DDevice->CreateIndexBuffer((mWidth * 6) * (mDepth * 6) * sizeof(WORD),
		D3DUSAGE_WRITEONLY,	D3DFMT_INDEX32, 
		D3DPOOL_MANAGED, &mIB, 0));

	DWORD* indices = 0;
	HR(mIB->Lock(0, 0, (void**)&indices, 0));

	int k = 0;
	for (unsigned int i = 0; i < mWidth-1; ++i)
	{
		for (unsigned int j = 0; j < mDepth-1; ++j)
		{
			indices[k + 0] = i * mDepth + j;
			indices[k + 1] = i * mDepth + (j + 1);
			indices[k + 2] = (i + 1) * mDepth + j;
			indices[k + 3] = (i + 1) * mDepth + j;
			indices[k + 4] = i * mDepth + (j + 1);
			indices[k + 5] = (i + 1) * mDepth + (j + 1);
			k += 6;
		}
	}

	HR(mIB->Unlock());
}
